<?php


namespace app\api\ctrl;


use app\service\Counter;
use app\service\LeakyBucket;
use app\service\TokenBucket;
use app\service\RedisLimit;
use app\service\FilterRepeatedContent;


/**
 * 限流、过滤
 * Class LimitCtrl
 * @package app\api\ctrl
 */
class LimitCtrl extends BaseCtrl
{
    /**
     * 简单计数器
     */
    public function counter()
    {
        $m = new Counter();
        $n_success = 0;
        for ($i = 0; $i < 200; $i++) {
            $rt = $m->grant();
            if ($rt) {
                $n_success++;
            }
        }
        echo '成功请求 ' . $n_success . ' 次';
    }

    /**
     * 漏斗桶
     */
    public function leak_bucket()
    {
        $m = new LeakyBucket();
        $n_success = 0;
        for ($i = 1; $i < 501; $i++) {
            $rt = $m->grant();
            if ($rt) {
                $n_success++;
            }
            if ($i % 100 == 0) {//每发起100次后暂停1s
                echo '已发送: ', $i, ', 成功: ', $n_success, ', sleep: 1s' . "<br/>";
                sleep(1);
            }
        }
        echo '成功请求 ' . $n_success . ' 次';
    }

    /**
     * 令牌桶
     */
    public function token_bucket()
    {
        $m = new TokenBucket();
        $n_success = 0;
        for ($i = 1; $i < 501; $i++) {
            $rt = $m->grant();
            if ($rt) {
                $n_success++;
            }
            if ($i % 100 == 0) {//每发起100次后暂停1s
                echo '已发送: ', $i, ', 成功: ', $n_success, ', sleep: 1s' . "<br/>";
                sleep(1);
            }
        }
        echo '成功请求 ' . $n_success . ' 次';
    }

    /**
     * ab -n 100 -c 100 http://127.0.0.1:82/api/limit/singleLimit
     * @return void
     */
    public function singleLimit()
    {
        $redisLimit = new RedisLimit();
        $uid = 1;
        $flag = $redisLimit->singleLimit($uid);
        debugLog($flag, 'limit');
        if ($flag) {
            echo $uid . ': success';
            debugLog('ok', 'singleLimit');
        } else {
            echo $uid . ': fail';
        }
    }

    /**
     * ab -n 100 -c 100 http://127.0.0.1:82/api/limit/globalLimit
     * @return void
     */
    public function globalLimit()
    {
        $reqUrl = 'baidu.com/a.php';
        $redisLimit = new RedisLimit();
        $uid = md5(uniqid(mt_rand(), true));
        $flag = $redisLimit->globalLimit($reqUrl);
        if ($flag) {
            echo $uid . ': success';
            debugLog('ok', 'globalLimit');
        } else {
            echo $uid . ': fail';
        }
    }

    /**
     * 限流：每M秒允许N个访问
     * @return void
     */
    public function isAllow() {
        $redisLimit = new RedisLimit();
        $uid = md5(uniqid(mt_rand(), true));
        $flag = $redisLimit->isAllow('test1');
        if ($flag) {
            debugLog($flag, 'isAllow');
            echo $uid . ': success';
        } else {
            echo $uid . ': fail';
        }
    }

    /**
     * 布隆过滤器
     */
    public function filter()
    {
        var_dump((new FilterRepeatedContent())->add('abc')); //true
        var_dump((new FilterRepeatedContent())->add('bcd')); //true
        var_dump((new FilterRepeatedContent())->add('dfg')); //true

        var_dump((new FilterRepeatedContent())->exists('dfg')); //true
        var_dump((new FilterRepeatedContent())->exists('dgg')); //false
    }
}